#coding:utf-8
# Create your views here.

from xml.dom.minidom import Document
from xml.dom import minidom
import datetime


import sys
sys.path.append('..')
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import settings
from django.shortcuts import get_object_or_404, render_to_response
from kspiderapp.models import ActionInfo,FileInfo
from django.http import HttpResponse

from dbUtil import InsertMultiDB,ExecuteSql
from dateTools import DateTime2Str,Str2DateTime
from log import Logger
import conf
from info import GetActionCount,GetFileInfo,GetUserCount,GetUserCountByRange,GetFileCountSizeByRange

CHART_XML_PATH =  settings.STATIC_PATH_templates 
USER_COUNT_XML_PATH = 'user_count.xml'
ACTION_COUNT_XML_PATH = 'action_count.xml'
FILE_SIZE_COUNT_XML_PATH = 'file_size_count.xml'



END_DATE = datetime.datetime.now()
#END_DATE = datetime.datetime(2010,9,16)
BEGIN_DATE = END_DATE - datetime.timedelta(days=1)
#BEGIN_DATE = datetime.datetime(2010,9,14)
 
def CreateErrorResponse(code, info=None):
    string = '<result code=\"%s\"' % code
    if info != None:
        string = '%s info=\"%s\"' % (string, info)
    string += ' />'
    return HttpResponse(string)



def InputUseinfo(request):
    try:
#        Logger.GetLogger().debug(str(request.POST ))    
        
        if request.POST.has_key(conf.USE_INFO):
            info = request.POST[conf.USE_INFO]
            category = conf.USE_INFO
        elif request.POST.has_key(conf.FILE_INFO):
            info = request.POST[conf.FILE_INFO]
            category = conf.FILE_INFO
        else:
            info = 'need parameter'
            return CreateErrorResponse(info)
        if type(info) == unicode:
            info = info.encode('utf8')
            
#        Logger.GetLogger().debug( 'info:%s category:%s' % (info, category))    
        result = ProcessXml(info, category)
        xml = CreateReturnXml(result)
        return HttpResponse(xml)
    except Exception, e:
        Logger.GetLogger().exception(e)
        return CreateErrorResponse('exception')



def Chart(request):
    try:
        result = CreateChartFile()
        if result:
            return render_to_response('dsChart.html',{})
        else:
            return CreateErrorResponse('ERROR', 'create Chart Failed!')
    except Exception, e:
        Logger.GetLogger().exception(e)
        return CreateErrorResponse('exception')
    
    
    
def Report(requset):
    
    try:
        reportData = GetReportData()
        Logger.GetLogger().debug(str(reportData))
        return render_to_response('totalData.html',
                              {'actionInfo':reportData['actionInfo'], 'userCount':reportData['userCount'],
                               'fileSize':reportData['fileSize'], 'fileCount':reportData['fileCount']})
    except Exception, e:
        Logger.GetLogger().exception(e)
        return CreateErrorResponse(code='exception', info='create Report Data Failed!')


def index(request):
    return render_to_response('chart.html',{})    
    

def GetReportData():
    beginDateStr = DateTime2Str(BEGIN_DATE)
    endDateStr = DateTime2Str(END_DATE)
    actionCount = GetActionCount(beginDateStr, endDateStr)
    actionInfo = []
    for action in actionCount:
        info = {'action':action, 'count':actionCount[action]}
        actionInfo.append(info)
        
    userCount = GetUserCount(beginDateStr, endDateStr)
    fileSize, fileCount = GetFileInfo(beginDateStr, endDateStr)
    
    if fileSize != None:
        fileSize /= 1024*1024
        fileSize = '%.2f MB' % fileSize
    else:
        fileSize = 0
        fileCount = 0
    
    report = {'actionInfo':actionInfo, 'userCount':userCount, 
              'fileSize':fileSize, 'fileCount':fileCount}
    
    return report
        
    

def CreateReturnXml(result):    
    code = result['code']
    info = result['info']
        
    doc = Document()
    # Create the base element root
    result = doc.createElement('result')
    result.setAttribute('code', code)
    if code != 'OK':
        result.setAttribute('info', info)
    
    doc.appendChild(result)
    xmlStr = doc.saveXML(result)
    return xmlStr
    
    
    
    

    
    
def WriteChartXml(xmlStr, path):
    '''将图表xml写入文件
    '''
    try:
        f = open(path,'w')
        f.write(xmlStr)
        f.close()
    except Exception,e:
        raise 
        

    
def GetDateTimeStep(dateLength):
    '''根据图表时间轴长度，计算得到横坐标步进
    '''
    if dateLength < 10:
        step = 1
    elif 10 <= dateLength < 15:
        step = 2
    elif 15 <= dateLength < 35:
        step = 4
    elif 35 <= dateLength < 50:
        step = 5
    elif dateLength >= 50:
        step = 7
    return step

    
    
def CreateChartFile():
    # 默认显示最近24小时的数据
    endDate = END_DATE
    beginDate = BEGIN_DATE
    try:    
        beginDateStr = DateTime2Str(beginDate)
        endDateStr = DateTime2Str(endDate)
        # 按每小时划分时间段,统计用户数
        dateCount = GetUserCountByRange(beginDateStr, endDateStr, dateFormat='%Y-%m-%d %H:00:00')
        xmlStr = CreateUserCountChartXml(dateCount)
        WriteChartXml(xmlStr, CHART_XML_PATH + '/'+ USER_COUNT_XML_PATH)
        
        # 功能使用次数统计
        actionCount = GetActionCount(beginDateStr, endDateStr)
        xmlStr = CreateActionCountChartXml(actionCount)
        WriteChartXml(xmlStr, CHART_XML_PATH + '/'+ ACTION_COUNT_XML_PATH)
        
        # 按每小时划分时间段, 文件大小和文件数时间分布
        fileSizeCount = GetFileCountSizeByRange(beginDateStr, endDateStr, dateFormat='%Y-%m-%d %H:00:00')
        xmlStr = CreateFileSizeCountChartXml(fileSizeCount)
        WriteChartXml(xmlStr, CHART_XML_PATH + '/'+ FILE_SIZE_COUNT_XML_PATH)
        
        
        
        return True
    except Exception,e:
        Logger.GetLogger().exception(e)
        return False
   
def CreateUserCountChartXml(dateCount):
    '''创建图表所需的xml
    dateCount: key为时间日期，value为count的一个字典对象。
    ''' 
    assert dateCount
    
    dateLen = len(dateCount) 
    # Create the minidom document 
    doc = Document()
    # Create the  base element root
    chart = doc.createElement('chart')
    
    chart.setAttribute('caption','user count')
    chart.setAttribute("yaxisname", "Count")
    chart.setAttribute("formatNumberScale", "1")
    chart.setAttribute("showSum","1")
    chart.setAttribute("xaxisname", "DateTime")
    chart.setAttribute("showValues","0")
    
    step = GetDateTimeStep(dateLen)
    chart.setAttribute("labelStep", str(step))
       
    for date in dateCount:
        count = dateCount[date]
        set = doc.createElement('set')
        set.setAttribute('label', str(date))
        set.setAttribute('value', str(count))
        chart.appendChild(set)

    doc.appendChild(chart)
    xmlStr = doc.toprettyxml(indent="  ")
    return xmlStr
   
   
   
    
    
def CreateFileSizeCountChartXml(fileSizeCount):
    '''
    
    PYAxisName='Sales' SYAxisName='Total Downloads'
    
    <chart caption='Business Results 2005 v 2006' xAxisName='Month' yAxisName='Revenue' showValues='0' numberPrefix='$'>
   <categories>
      <category label='Jan' />
      <category label='Feb' />
      <category label='Mar' />
      <category label='Apr' />
      <category label='May' />
      <category label='Jun' />
      <category label='Jul' />
      <category label='Aug' />
      <category label='Sep' />
      <category label='Oct' />
      <category label='Nov' />
      <category label='Dec' />
   </categories>

   <dataset seriesName='2006'>
      <set value='27400' />
      <set value='29800'/>
      <set value='25800' />
      <set value='26800' />
      <set value='29600' />
      <set value='32600' />
      <set value='31800' />
      <set value='36700' />
      <set value='29700' />
      <set value='31900' />
      <set value='34800' />
      <set value='24800' />
   </dataset>

   <dataset seriesName='2005'>
      <set value='10000'/>
      <set value='11500'/>
      <set value='12500'/>
      <set value='15000'/>
      <set value='11000' />
      <set value='9800' />
      <set value='11800' />
      <set value='19700' />
      <set value='21700' />
      <set value='21900' />
      <set value='22900' />
      <set value='20800' />
   </dataset>
    '''
    doc = Document()
    # Create the  base element root
    chart = doc.createElement('chart')
    chart.setAttribute('caption','file_size_count')
    chart.setAttribute("PYAxisName", "fileSize")
    chart.setAttribute("SYAxisName", "fileCount")
    chart.setAttribute("showvalues", "0")
       
       
    categories = doc.createElement('categories')
        
    datesetSize = doc.createElement('dataset')
    datesetSize.setAttribute('seriesName', 'file_size')
    datesetSize.setAttribute('renderAs', 'line')
    datesetSize.setAttribute('parentYAxis', 'P')
    
    datesetCount = doc.createElement('dataset')
    datesetCount.setAttribute('seriesName', 'file_count')
    datesetCount.setAttribute('parentYAxis', 'S')
    
    for date in fileSizeCount:
        category = doc.createElement('category')
        category.setAttribute('label', str(date))
        categories.appendChild(category)
        size = fileSizeCount[date]['size']
        count = fileSizeCount[date]['count']
        
        set = doc.createElement('set')
        set.setAttribute('value', str(size))
        datesetSize.appendChild(set)
        
        set = doc.createElement('set')
        set.setAttribute('value', str(count))
        datesetCount.appendChild(set)

    
    chart.appendChild(categories)
    chart.appendChild(datesetCount)
    chart.appendChild(datesetSize)
    doc.appendChild(chart)
    xmlStr = doc.toprettyxml(indent="  ")
    return xmlStr
    
    
def CreateActionCountChartXml(actionCount):
    '''操作次数统计，饼图
    <chart caption='Company Revenue' showPercentageValues='1'>
       <set label='Services' value='26' />
       <set label='Hardware' value='32' />
       <set label='Software' value='42' />
    </chart> 
    
    '''
    doc = Document()
    # Create the  base element root
    chart = doc.createElement('chart')
    
    chart.setAttribute('caption','action_count')
    
    for action in actionCount:
        count = actionCount[action]
        set = doc.createElement('set')
        set.setAttribute('label', str(action))
        set.setAttribute('value', str(count))
        chart.appendChild(set)
    
    doc.appendChild(chart)
    xmlStr = doc.toprettyxml(indent="  ")
    return xmlStr
   


def ProcessXml(xml, type):
    result = {'code':'OK','info':''}
    try:
        if type == conf.USE_INFO:
            ProcessUseInfo(xml)
        elif type == conf.FILE_INFO:
            ProcessFileInfo(xml)
        
    except Exception, e:
        result['code'] = 'ERROR'
        result['info'] = 'Procss xml error!'
	Logger.GetLogger().debug('error xml:'+ xml)
        Logger.GetLogger().exception(e)

    return result
    
        
    
    
def ProcessUseInfo(xml):
    useInfoList = GetUseInfoList(xml)
#    for useInfo in useInfoList:
#        print useInfo
    
    InsertUseInfo(useInfoList)
    
def ProcessFileInfo(xml):
    fileInfoList = GetFileInfoList(xml)
#    for fileInfo in fileInfoList:
#        print fileInfo
        
    InsertFileInfo(fileInfoList)
 
    
def GetTextNodeValue(node):
    return node.childNodes[0].nodeValue.encode('utf8')
    
def GetUseInfoList(useInfoXml):
    try:
        xml = '<root>\n' + useInfoXml + '\n</root>'
        dom = minidom.parseString(xml)
        rootElement = dom.getElementsByTagName('root')[0]
        useinfoElements = rootElement.getElementsByTagName(conf.USE_INFO)
        useInfoList = []
        
        for useinfo in useinfoElements:
            timeValue = GetTextNodeValue(useinfo.getElementsByTagName('time')[0] )
            userValue = GetTextNodeValue(useinfo.getElementsByTagName('user')[0] )
            action = GetTextNodeValue(useinfo.getElementsByTagName('action')[0] )
            code = GetTextNodeValue(useinfo.getElementsByTagName('code')[0] )
            infoNode = useinfo.getElementsByTagName('info')
            info = ''
            if infoNode is not None and len(infoNode) > 0:
                info = GetTextNodeValue(infoNode[0] )
            
            useinfoObj = [timeValue, userValue, action, code, info]
            useInfoList.append(useinfoObj)
            
        return useInfoList
    except Exception,e:
        raise
        


def GetFileInfoList(fileInfoXml):
    try:
        xml = '<root>\n' + fileInfoXml + '\n</root>'
        dom = minidom.parseString(xml)
        rootElement = dom.getElementsByTagName('root')[0]
        fileInfoElements = rootElement.getElementsByTagName(conf.FILE_INFO)
        fileInfoList = []
        
        for fileInfo in fileInfoElements:
            timeValue = GetTextNodeValue(fileInfo.getElementsByTagName('time')[0] )
            userValue = GetTextNodeValue(fileInfo.getElementsByTagName('user')[0] )
            filesize = GetTextNodeValue(fileInfo.getElementsByTagName('filesize')[0] )
            filecount = GetTextNodeValue(fileInfo.getElementsByTagName('filecount')[0] )
            fileInfoObj = [timeValue, userValue, filesize, filecount]
            fileInfoList.append(fileInfoObj)
            
        return fileInfoList
    except Exception,e:
        raise

    
def InsertUseInfo(useInfoList):
    table = conf.ACTIONINFO_TABLE
    fields = ('date_time', 'user', 'action', 'code', 'info')
    try:
        count = InsertMultiDB(table, fields, useInfoList)
        Logger.GetLogger().debug('insert useInfoTable count:%d' % count)
    except Exception,e:
        raise
    
def InsertFileInfo(fileInfoList):
    table = conf.FILEINFO_TABLE
    fields = ('date_time', 'user', 'file_size', 'file_count')
    try:
        count = InsertMultiDB(table, fields, fileInfoList)
        Logger.GetLogger().debug('insert fileInfoTable count:%d' % count)
    except Exception,e:
        raise




if __name__ == '__main__':
    string =   '''
    <useinfo>
    <time>2010-09-23 10:02:20</time>
    <user>lijun</user>
    <action>addNote</action>
    <code>ERROR</code>
    <info>server internal error</info>
    </useinfo>
    <useinfo>
    <time>2010-09-24 10:02:20</time>
    <user>lijun</user>
    <action>addNote</action>
    <code>OK</code>
    </useinfo>
   ''' 
#    ProcessXml(string, conf.USE_INFO)
#    
#    string = '''
#    <fileinfo>
#    <time>2010-09-23 10:02:20</time>
#    <user>lijun</user>
#    <filesize>202934</filesize>
#    <filecount>105</filecount>
#    </fileinfo>
#    '''
#    ProcessXml(string, conf.FILE_INFO)
    
    
#    sql = r"insert into kspiderapp_actioninfo(date_time,user,action,code,info) values ('2010-09-30','fff','del','OK','aaa');"
#    ExecuteSql(sql)
    
    dateCount= {'2010-10-01 11:00':2568, 
                '2010-10-01 12:00':2102, 
                '2010-10-01 13:00':1235, 
                '2010-10-01 14:00':3562}
    
#    print CreateChart(dateCount, startDate=None, endDate=None)

    CreateChartFile()

